package service

import (
	"crypto/tls"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/http"
	"time"

	"com.zkh/agent/coap/conf"
	"com.zkh/agent/coap/global"
	"com.zkh/agent/coap/objs"
	"github.com/gin-gonic/gin"
	"github.com/go-resty/resty/v2"
	"github.com/patrickmn/go-cache"
	"github.com/plgd-dev/go-coap/v3/message"
	"github.com/plgd-dev/go-coap/v3/message/codes"
)

var reqIdCache *cache.Cache

func init() {
	// 创建缓存，设置默认过期时间60秒，每10分钟清除过期项
	reqIdCache = cache.New(60*time.Second, 10*time.Minute)
}

func DoCmd(c *gin.Context) {
	returnData := objs.HttpResp{Code: 200, Msg: "操作成功"}
	body, _ := io.ReadAll(c.Request.Body)
	var cmd objs.HttpReq
	json.Unmarshal(body, &cmd)
	log.Printf("DoCmd recive : %v\n", cmd)

	opts := objs.MapToOptions(cmd.Option)
	dev_id, _ := opts.GetString(objs.DEV_ID)

	client, err := global.CoapServer.Manager.Get(dev_id)
	if err != nil {
		log.Printf("DoCmd coap Client error! %v", err)
		returnData.Code = 500
		returnData.Msg = fmt.Sprintf("DoCmd coap 发送失败 error! %v ", err)
		c.JSON(http.StatusOK, returnData)
		return
	} else {
		go func() {
			token, _ := message.GetToken()
			log.Printf("DoCmd send data : %v\n", cmd)

			code, err := codes.ToCode(cmd.Method)
			if err != nil {
				code = codes.POST
			}

			client.SendCoapMsg(dev_id, cmd.Url, token, code, message.TextPlain, []byte(cmd.Body), opts...)

			tdchannel := make(chan objs.HttpCoapRet, 1)
			defer close(tdchannel)
			reqIdCacheKey := dev_id + "-" + cmd.Option["REQ_ID"]
			// 缓存下发的ID
			reqIdCache.Set(reqIdCacheKey, tdchannel, 60*time.Second)

			select { //下面的case只执行最早到来的那一个
			case retData := <-tdchannel: //LongTimeWork运行结束
				returnData.Data = retData
			case <-time.After(65 * time.Second): //timeout到来
				log.Printf("DoCmd 下发响应超时！DevId=%s,ReqId=%s,path=%s\n", dev_id, cmd.Option["REQ_ID"], cmd.Url)
				returnData.Code = 444
				returnData.Msg = "响应超时！"
			}
			reqIdCache.Delete(reqIdCacheKey)
			c.JSON(http.StatusOK, returnData)
		}()
	}

}

func SendToCloudCmd(reqObj objs.HttpReq) (returnData objs.HttpResp, err error) {
	apiUrl := conf.GetDeviceCloudHost()
	client := resty.New().SetTimeout(10 * time.Second).SetTLSClientConfig(&tls.Config{InsecureSkipVerify: true}) //忽略https证书错误，设置超时时间
	req := client.R()
	req.SetHeader("Content-Type", "application/json")
	req.SetBody(reqObj)
	log.Printf("SendToCloudCmd 转发请求:url:%s;Option:%v;body=%s\n", reqObj.Url, reqObj.Option, reqObj.Body)
	resp, err := req.EnableTrace().Post(apiUrl)
	if err != nil {
		log.Printf(" SendToCloudCmd 转发错误:%v\n", err)
		return returnData, err
	}
	json.Unmarshal(resp.Body(), &returnData)
	log.Printf("SendToCloudCmd 请求返回:%+v \n", returnData)
	return returnData, err
}
